home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------------------------------
- *
- * Simple Sample PowerTalk Application Framework
- *
- * ©1991-1993 Apple Computer
- *
- -------------------------------------------------------------------------------------*/
- /*
- * digisig.c -- digital signature stuff
- *
- * change history:
- *
- * SJF 08/23/93 1.0f1 update to final headers, fix comments
- * SJF 03/08/93 1.0b1 initial coding
- *
- */
-
- #pragma segment othersegment
-
- #ifndef __TYPES__
- #include <Types.h>
- #endif
-
- #ifndef __MENUS__
- #include <Menus.h>
- #endif
-
- #ifndef __FOLDERS__
- #include <Folders.h>
- #endif
-
- #ifndef __FILES__
- #include <Files.h>
- #endif
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef __RESOURCES__
- #include <Resources.h>
- #endif
-
- #ifndef __GESTALTEQU__
- #include <GestaltEqu.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- #ifndef __DIGITALSIGNATURE__
- #include <DigitalSignature.h>
- #endif
-
- #include "const.h"
- #include "mytypes.h"
- #include "globals.h"
- #include "utils.h"
- #include "windowstuff.h"
- #include "strconst.h"
- #include "mymenus.h"
- #include "draw.window.h"
- #include "IconSuites.h"
-
- #include "digisig.h"
-
- #define kDSIGPattern 7 // we're using the black diagonal lines pattern
- #define kDSIGFrameSize 2 // our pattern outline frame is 2 pixels wide
-
- // static globals
-
- static short gDSTempRefNum; // temporary digital signature storage file refnum
- static FSSpec gDSTempFSpec; // temporary digital signature storage file FSSpec
-
- // routines
-
- /** HasDigiSign
- **
- ** returns true only of Digital Signature package is available and running
- **/
- Boolean HasDigiSign(void)
- {
- OSErr err;
- long response;
-
- err = Gestalt(gestaltDigitalSignatureVersion,&response);
- if ((err!=noErr) || (response==0))
- return false;
-
- return true;
- }
-
-
- /** InitDigitalSignatures
- **
- ** called once at launch to set up temporary files for digital signature handling
- **/
- OSErr InitDigitalSignatures(void)
- {
- OSErr err;
-
- gShowSigners = false;
-
- err = FindFolder(kOnSystemDisk,kTemporaryFolderType,true,&gDSTempFSpec.vRefNum,
- &gDSTempFSpec.parID);
- if (err!=noErr)
- return err;
- GetResString((StringPtr)&gDSTempFSpec.name,kTempDSFileID,kTempDSFile);
-
- FSpCreateResFile(&gDSTempFSpec,kAppCreator,'????',smRoman);
- if (ResError()==dupFNErr) {
- FSpDelete(&gDSTempFSpec);
- FSpCreateResFile(&gDSTempFSpec,kAppCreator,'????',smRoman);
- }
- if (ResError()==noErr)
- gDSTempRefNum = FSpOpenResFile(&gDSTempFSpec,fsRdWrPerm);
-
- return ResError();
- }
-
-
- /** ExitDigitalSignatures
- **
- ** called once at quit to get rid of temporary files for digital signature handling
- **/
- void ExitDigitalSignatures(void)
- {
- CloseResFile(gDSTempRefNum);
- FSpDelete(&gDSTempFSpec);
- }
-
-
- /** DSIGSetupSignMenu
- **
- ** called to set up the signatures menu for a particular window- enables and disables items
- **/
- void DSIGSetupSignMenu(WInfoPtr infoPtr)
- {
- MenuHandle theMenu;
- ShapeListPtr shapeList;
- Boolean gotSigned;
-
- theMenu = GetMHandle(kSignMenu);
-
- if (!gHasDigiSign) {
- DisableItem(theMenu,0);
- return;
- }
-
- EnableAllMenuItems(theMenu);
-
- if (!CheckShapeSelected(infoPtr))
- DisableItem(theMenu,kSignItem);
-
- gotSigned = false;
- for (shapeList=infoPtr->data; shapeList!=nil; shapeList=shapeList->next) {
- if ((shapeList->isSigned) && (shapeList->selected))
- gotSigned = true;
- }
- if (!gotSigned)
- DisableItem(theMenu,kVerifyItem);
-
- CheckItem(theMenu,kShowSignItem,gShowSigners);
- }
-
-
- /** DSIGOpenFile
- **
- ** called when a document is opened to get a record of which shapes are signed
- **/
- void DSIGOpenFile(WInfoPtr infoPtr)
- {
- DigSigListPtr dsigList,newDSIG;
- ShapeListPtr shapeList;
-
- dsigList = nil;
-
- for (shapeList=infoPtr->data; shapeList!=nil; shapeList=shapeList->next) {
- if (shapeList->isSigned) {
- newDSIG = NewPtrChk(sizeof(DigSigList));
- if (MemError()!=noErr)
- return;
- newDSIG->shape = shapeList;
- newDSIG->signatureID = shapeList->signatureID;
- newDSIG->inTemp = false;
- newDSIG->shouldDelete = false;
- newDSIG->next = dsigList;
- dsigList = newDSIG;
- shapeList->digSig = newDSIG;
- }
- else
- shapeList->digSig = nil;
- }
-
- infoPtr->otherData[kDSIGData] = dsigList;
- }
-
-
- /** DSIGCloseFile
- **
- ** called when a document is closed in order to remove any digital signatures
- ** from the temporary digital signature file
- **/
- void DSIGCloseFile(WInfoPtr infoPtr)
- {
- DigSigListPtr dsigList,prevSig;
- short saveResFile;
- Handle resHandle;
-
- saveResFile = CurResFile();
- UseResFile(gDSTempRefNum);
-
- dsigList=infoPtr->otherData[kDSIGData];
- while (dsigList!=nil) {
- if (dsigList->inTemp) {
- SetResLoad(false);
- resHandle = Get1Resource(kSignatureResType,dsigList->signatureID);
- RmveResource(resHandle);
- SetResLoad(true);
- }
- prevSig = dsigList;
- dsigList = dsigList->next;
- DisposPtrChk(prevSig);
- }
- infoPtr->otherData[kDSIGData] = nil;
-
- UpdateResFile(gDSTempRefNum);
- UseResFile(saveResFile);
- }
-
-
- /** DSIGSaveFile
- **
- ** called when a document is saved in order to flush any digital signatures back to disk
- ** from the temporary digital signature file
- **/
- void DSIGSaveFile(WInfoPtr infoPtr,short newResRef,Boolean saveACopy)
- {
- short saveResFile,oldResRef;
- short newID;
- DigSigListPtr dsigList,oldSig,prevSig;
- Handle resHandle;
-
- oldResRef = infoPtr->resRefNum;
- saveResFile = CurResFile();
-
- prevSig = nil;
- dsigList=infoPtr->otherData[kDSIGData];
- while (dsigList!=nil) {
- if (dsigList->shouldDelete && (dsigList->inTemp ||
- (!saveACopy && (oldResRef==newResRef)))) {
-
- // delete sig resource
-
- if (dsigList->inTemp)
- UseResFile(gDSTempRefNum);
- else
- UseResFile(oldResRef);
- SetResLoad(false);
- resHandle = Get1Resource(kSignatureResType,dsigList->signatureID);
- RmveResource(resHandle);
- SetResLoad(true);
-
- // delete old dsig object from list
-
- if (prevSig)
- prevSig->next = dsigList->next;
- else
- infoPtr->otherData[kDSIGData] = dsigList->next;
-
- oldSig = dsigList;
- dsigList = dsigList->next;
- DisposPtrChk(oldSig);
- }
- else if (dsigList->inTemp || saveACopy) {
-
- // copy sig resource from temp file (or old doc file) to new document file
-
- if (dsigList->inTemp) {
- if (!saveACopy) {
- UseResFile(newResRef);
- newID = Unique1ID(kSignatureResType);
- }
- else
- newID = dsigList->signatureID;
- UseResFile(gDSTempRefNum);
- }
- else {
- newID = dsigList->signatureID; // keep same ID for save a copy saves
- UseResFile(oldResRef);
- }
- resHandle = Get1Resource(kSignatureResType,dsigList->signatureID);
- DetachResource(resHandle);
- UseResFile(newResRef);
- AddResource(resHandle,kSignatureResType,newID,"\p");
- if (ResError()!=noErr) {
- DoError(ResError());
- return;
- }
-
- // re-point objects to new ID
-
- if (saveACopy==false)
- dsigList->inTemp = false;
- dsigList->signatureID = newID;
- dsigList->shape->signatureID = newID;
- }
-
- if (dsigList->shouldDelete==false) {
- prevSig = dsigList;
- dsigList = dsigList->next;
- }
- }
-
- UpdateResFile(gDSTempRefNum);
- if (oldResRef)
- UpdateResFile(oldResRef);
- UpdateResFile(newResRef);
- UseResFile(saveResFile);
- }
-
-
- /** DSIGCopySigsToTemp
- **
- ** needed for add/remove mailer, since this disconnects the data from the document, where
- ** the signatures are stored. this function copies all of these signature resources into the
- ** temp file when the user does add or remove mailer
- **/
- void DSIGCopySigsToTemp(WInfoPtr infoPtr)
- {
- DigSigListPtr dsigList;
- short saveResFile,docResFile;
- Handle resHandle;
- short newID;
-
- saveResFile = CurResFile();
- docResFile = infoPtr->resRefNum;
-
- dsigList=infoPtr->otherData[kDSIGData];
- while (dsigList!=nil) {
- if (dsigList->inTemp==false) {
- UseResFile(docResFile);
- resHandle = Get1Resource(kSignatureResType,dsigList->signatureID);
- DetachResource(resHandle);
- UseResFile(gDSTempRefNum);
- newID = Unique1ID(kSignatureResType);
- AddResource(resHandle,kSignatureResType,newID,"\p");
- if (ResError()!=noErr) {
- DoError(ResError());
- return;
- }
- dsigList->signatureID = newID;
- dsigList->shape->signatureID = newID;
- dsigList->inTemp = true;
- }
- dsigList = dsigList->next;
- }
-
- UpdateResFile(gDSTempRefNum);
- UpdateResFile(docResFile);
- UseResFile(saveResFile);
- }
-
-
- /** DSIGDrawSigner
- **
- ** draws the signer outline and icon around a shape if it's signed and gShowSigners is true
- **/
- void DSIGDrawSigner(ShapeListPtr theShape,Point drawOffset)
- {
- Rect iconRect;
- Pattern pat;
-
- if (!theShape->isSigned)
- return;
-
- if (!gShowSigners)
- return;
-
- SetRect(&iconRect,theShape->anchor.h+drawOffset.h,theShape->anchor.v+drawOffset.v,
- theShape->destination.h+drawOffset.h,theShape->destination.v+drawOffset.v);
- FixRect(&iconRect);
-
- #ifdef dangerousPattern
- GetIndPattern(pat,sysPatListID,kDSIGPattern);
- PenPat(pat);
- #else
- GetIndPattern(&pat,sysPatListID,kDSIGPattern);
- PenPat(&pat);
- #endif
- PenSize(kDSIGFrameSize,kDSIGFrameSize);
- FrameRect(&iconRect);
- PenNormal();
-
- iconRect.left = iconRect.right - 16;
- iconRect.top = iconRect.bottom - 16;
- PlotIconID(&iconRect,atNone,ttNone,256);
- }
-
-
- /** DSIGHitShape
- **
- ** checks to see if we hit the little signature icon on this shape
- **/
- Boolean DSIGHitShape(WInfoPtr infoPtr,Point hitPt,Point offsetPos,ShapeListPtr theShape)
- {
- Rect dsigBox;
- Boolean returnVal,hitBox;
- Point mousePt;
- SIGContextPtr sigContext;
- OSErr err;
-
- SetRect(&dsigBox,theShape->anchor.h+offsetPos.h,theShape->anchor.v+offsetPos.v,
- theShape->destination.h+offsetPos.h,theShape->destination.v+offsetPos.v);
- FixRect(&dsigBox);
- dsigBox.left = dsigBox.right-16;
- dsigBox.top = dsigBox.bottom-16;
-
- hitBox = false;
- if (gShowSigners && PtInRect(hitPt,&dsigBox) && theShape->isSigned) {
- while (WaitMouseUp()) {
- GetMouse(&mousePt);
- if (PtInRect(mousePt,&dsigBox)) {
- if (!hitBox) {
- hitBox = true;
- PlotIconID(&dsigBox,atNone,ttNone,257);
- }
- }
- else {
- if (hitBox) {
- hitBox = false;
- PlotIconID(&dsigBox,atNone,ttNone,256);
- }
- }
- }
- PlotIconID(&dsigBox,atNone,ttNone,256);
-
- // verify the selected shape
-
- if (hitBox) {
- err = SIGNewContext(&sigContext);
- if (err==noErr) {
- err = VerifyShape(infoPtr,sigContext,theShape);
- SIGDisposeContext(sigContext);
- }
- if (err!=noErr)
- DoError(err);
- }
-
- returnVal = true;
- }
- else returnVal = false;
- return returnVal;
- }
-
-
- /** CommSign
- **
- ** high level call to sign the selected shapes, called in response to "Sign Selected Shapes..."
- **/
- void CommSign(WindowPtr window)
- {
- WInfoPtr infoPtr;
- char hState;
- ShapeListPtr shapeList;
- SIGContextPtr sigContext;
- Size sigSize;
- OSErr err;
-
- if (!IsAppWindow(window))
- return;
-
- err = SIGNewContext(&sigContext);
-
- if (err==noErr) {
-
- infoPtr = BeginWindowAccess(window,&hState);
-
- if (err==noErr)
- err = SIGSignPrepare(sigContext,nil,nil,&sigSize);
-
- for (shapeList=infoPtr->data; (err==noErr)&&(shapeList!=nil); shapeList=shapeList->next) {
- if (shapeList->selected)
- err = SignShape(infoPtr,sigContext,shapeList,sigSize);
- InvalShapeArea(window,infoPtr,shapeList);
- }
-
- SIGDisposeContext(sigContext);
- DSIGSetupSignMenu(infoPtr);
- EndWindowAccess(window,hState);
- }
-
- if (err!=noErr)
- DoError(err);
- }
-
-
- /** CommVerify
- **
- ** high level call to verify the selected shapes, called in response to"Verify Selected Shapes..."
- **/
- void CommVerify(WindowPtr window)
- {
- WInfoPtr infoPtr;
- char hState;
- ShapeListPtr shapeList;
- SIGContextPtr sigContext;
- OSErr err;
-
- if (!IsAppWindow(window))
- return;
-
- err = SIGNewContext(&sigContext);
- if (err==noErr) {
-
- infoPtr = BeginWindowAccess(window,&hState);
-
- for (shapeList=infoPtr->data; (err==noErr)&&(shapeList!=nil); shapeList=shapeList->next) {
- if (shapeList->selected)
- err = VerifyShape(infoPtr,sigContext,shapeList);
- }
-
- SIGDisposeContext(sigContext);
- EndWindowAccess(window,hState);
- }
-
- if (err!=noErr)
- DoError(err);
- }
-
-
- /** CommShowSigners
- **
- ** shows or hides the signer icons/outlines in any signed shapes
- **/
- void CommShowSigners(WindowPtr window)
- {
- WInfoPtr infoPtr;
- char hState;
- ShapeListPtr shapeList;
-
- if (!IsAppWindow(window))
- return;
-
- infoPtr = BeginWindowAccess(window,&hState);
-
- gShowSigners = !gShowSigners;
-
- for (shapeList=infoPtr->data; shapeList!=nil; shapeList=shapeList->next) {
- if (shapeList->isSigned)
- InvalShapeArea(window,infoPtr,shapeList);
- }
-
- DSIGSetupSignMenu(infoPtr);
-
- EndWindowAccess(window,hState);
- }
-
-
- /*----------------------------------------------------------------------------------------------*/
- /* local calls inside this file */
- /*----------------------------------------------------------------------------------------------*/
-
- /** SignShape
- **
- ** signs a given shape using the passed in context and required signature size
- **/
- OSErr SignShape(WInfoPtr infoPtr,SIGContextPtr sigContext,ShapeListPtr theShape,Size sigSize)
- {
- OSErr err;
- Handle signature;
- short resID;
- short saveResFile;
- DigSigListPtr theSig;
-
- // allocate storage for the signature
-
- signature = NewHandleChk(sigSize);
- if (MemError()!=noErr)
- return MemError();
-
- // process the data for the signature
-
- err = ProcessShapeData(sigContext,theShape);
- if (err!=noErr) {
- DisposHandleChk(signature);
- return err;
- }
-
- // create the signature
-
- HLock(signature);
- err = SIGSign(sigContext,(SIGSignaturePtr)*signature,nil);
- HUnlock(signature);
-
- // bail if the sign didn't succeed
-
- if (err!=noErr)
- return err;
-
- // add the signature to the shape
-
- saveResFile = CurResFile();
- UseResFile(gDSTempRefNum);
- resID = Unique1ID(kSignatureResType);
- AddResource(signature,kSignatureResType,resID,"\p");
- if (ResError()==noErr) {
-
- ReleaseResource(signature);
-
- // see if old shape is already signed-- if so, mark the old signature for deletion
-
- if (theShape->isSigned) {
- theSig = theShape->digSig;
- theSig->shouldDelete = true;
- }
-
- // create the signature object and add it to the list, ref to shape
-
- theSig = NewPtrChk(sizeof(DigSigList));
- if (MemError()!=noErr)
- return MemError();
- theSig->shape = theShape;
- theSig->inTemp = true;
- theSig->shouldDelete = false;
- theSig->next = infoPtr->otherData[kDSIGData];
- infoPtr->otherData[kDSIGData] = theSig;
- theSig->signatureID = resID;
-
- theShape->digSig = theSig;
- theShape->signatureID = resID;
- theShape->isSigned = true;
- }
- else {
- DisposHandleChk(signature);
- err = ResError();
- }
- UpdateResFile(gDSTempRefNum);
- UseResFile(saveResFile);
-
- return err;
- }
-
-
- /** VerifyShape
- **
- ** verifies a given shape using the passed in context
- **/
- OSErr VerifyShape(WInfoPtr infoPtr,SIGContextPtr sigContext,ShapeListPtr theShape)
- {
- DigSigListPtr theSig;
- short saveResFile;
- Handle sigHandle;
- OSErr err;
- Size signatureSize;
-
- if (theShape->isSigned==false)
- return noErr;
-
- theSig = theShape->digSig;
-
- saveResFile = CurResFile();
- if (theSig->inTemp)
- UseResFile(gDSTempRefNum);
- else
- UseResFile(infoPtr->resRefNum);
- sigHandle = Get1Resource(kSignatureResType,theSig->signatureID);
- err = ResError();
- UseResFile(saveResFile);
- if (err!=noErr)
- return err;
-
- signatureSize = SizeResource(sigHandle);
- HLock(sigHandle);
- err = SIGVerifyPrepare(sigContext,(SIGSignaturePtr)*sigHandle,signatureSize,nil);
- if (err==noErr) {
-
- // process the data for the signature
- err = ProcessShapeData(sigContext,theShape);
- if (err==noErr) {
- err = SIGVerify(sigContext);
- if (err==noErr)
- err = SIGShowSigner(sigContext,nil);
- }
- }
-
- ReleaseResource(sigHandle);
- return err;
- }
-
-
- /** ProcessShapeData
- **
- ** digests the shape data for the signature. may be called recursively for group shapes
- **/
- OSErr ProcessShapeData(SIGContextPtr sigContext,ShapeListPtr theShape)
- {
- OSErr err;
- ShapeListPtr shapeList;
-
- err = noErr;
- if (theShape->shapeType==kBeginGroupTag) {
- for (shapeList=theShape->subList; (shapeList!=nil) && (err==noErr);
- shapeList=shapeList->next)
- err = ProcessShapeData(sigContext,shapeList);
- }
- else
- err = SIGProcessData(sigContext,theShape,kShapeSignLength);
- return err;
- }